﻿////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// <copyright>Copyright 2008-2011 Andreas Huber Doenni</copyright>
// Distributed under the GNU General Public License version 2 (GPLv2).
// See accompanying file License.txt or copy at http://phuse.codeplex.com/license.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

namespace Phorums
{
    using System;
    using System.Collections.Generic;
    using System.IO.IsolatedStorage;
    using System.Security.Cryptography;
    using System.Windows;
    using System.Windows.Navigation;
    using Microsoft.Phone.Controls;
    using Microsoft.Phone.Shell;

    using Phuse.Net.Forums;

    /// <summary>Represents the application.</summary>
    public partial class App : Application
    {
        private Cache cache;

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>Initializes a new instance of the <see cref="App"/> class.</summary>
        public App()
        {
            // Global handler for uncaught exceptions. 
            this.UnhandledException += this.Application_UnhandledException;

            // Standard Silverlight initialization
            this.InitializeComponent();

            // Phone-specific initialization
            this.InitializePhoneApplication();

            // Show graphics profiling information while debugging.
            if (System.Diagnostics.Debugger.IsAttached)
            {
                // Display the current frame rate counters.
                Application.Current.Host.Settings.EnableFrameRateCounter = true;

                // Show the areas of the app that are being redrawn in each frame.
                // Application.Current.Host.Settings.EnableRedrawRegions = true;

                // Enable non-production analysis visualization mode, 
                // which shows areas of a page that are handed off to GPU with a colored overlay.
                // Application.Current.Host.Settings.EnableCacheVisualization = true;

                // Disable the application idle detection by setting the UserIdleDetectionMode property of the
                // application's PhoneApplicationService object to Disabled.
                // Caution:- Use this under debug mode only. Application that disables user idle detection will continue to run
                // and consume battery power when the user is not using the phone.
                PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Disabled;
            }
        }

        /// <summary>
        /// Provides easy access to the root frame of the Phone Application.
        /// </summary>
        /// <returns>The root frame of the Phone Application.</returns>
        public PhoneApplicationFrame RootFrame { get; private set; }

        /// <summary>Gets the cache of the application.</summary>
        public Cache Cache
        {
            get { return this.cache; }
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        private static string GetValue(string valueName)
        {
            try
            {
                return (string)IsolatedStorageSettings.ApplicationSettings[valueName];
            }
            catch (KeyNotFoundException)
            {
                return null;
            }
        }

        private static void SetValue(string valueName, string value)
        {
            IsolatedStorageSettings.ApplicationSettings[valueName] = value;
            IsolatedStorageSettings.ApplicationSettings.Save();
        }

        // Code to execute when the application is launching (eg, from Start)
        // This code will not execute when the application is reactivated
        private void Application_Launching(object sender, LaunchingEventArgs e)
        {
            var dataDirectory = "Data";

            try
            {
                Cache.CreateCache(dataDirectory);
            }
            catch (ArgumentException)
            {
                // Articles already downloaded
                this.cache = new Cache(dataDirectory, new CryptoProvider());
                return;
            }

            this.cache = new Cache(dataDirectory, new CryptoProvider());
            var host = this.cache.AddHost<NntpForumProvider, NntpConnection>("thunderbolt", 119);
            var group = host.AddGroup("our.group", "Our Group", 5000, 5000);

            // var host = cache.AddHost(
            //     "news.giganews.com", 119, "Andreas Huber", "ahd6974-spamboostorgtrap@yahoo.com",
            //     GetValue("AccountName"), GetValue("Password"));
            // var group = host.AddGroup("alt.test", "Test", 50, 50);
            // var host = cache.AddHost("news.gmane.org", 119);
            // var group = host.AddGroup("gmane.comp.lib.boost.devel", "Boost Developers", 500, 500);
            this.cache.SaveChanges();
        }

        // Code to execute when the application is activated (brought to foreground)
        // This code will not execute when the application is first launched
        private void Application_Activated(object sender, ActivatedEventArgs e)
        {
        }

        // Code to execute when the application is deactivated (sent to background)
        // This code will not execute when the application is closing
        private void Application_Deactivated(object sender, DeactivatedEventArgs e)
        {
        }

        // Code to execute when the application is closing (eg, user hit Back)
        // This code will not execute when the application is deactivated
        private void Application_Closing(object sender, ClosingEventArgs e)
        {
            this.cache.Dispose();
        }

        // Code to execute if a navigation fails
        private void RootFrame_NavigationFailed(object sender, NavigationFailedEventArgs e)
        {
            if (System.Diagnostics.Debugger.IsAttached)
            {
                // A navigation has failed; break into the debugger
                System.Diagnostics.Debugger.Break();
            }
        }

        // Code to execute on Unhandled Exceptions
        private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
        {
            if (System.Diagnostics.Debugger.IsAttached)
            {
                // An unhandled exception has occurred; break into the debugger
                System.Diagnostics.Debugger.Break();
            }
        }

        // Avoid double-initialization
        private bool phoneApplicationInitialized = false;

        // Do not add any additional code to this method
        private void InitializePhoneApplication()
        {
            if (this.phoneApplicationInitialized)
            {
                return;
            }

            // Create the frame but don't set it as RootVisual yet; this allows the splash
            // screen to remain active until the application is ready to render.
            this.RootFrame = new PhoneApplicationFrame();
            this.RootFrame.Navigated += this.CompleteInitializePhoneApplication;

            // Handle navigation failures
            this.RootFrame.NavigationFailed += this.RootFrame_NavigationFailed;

            // Ensure we don't initialize again
            this.phoneApplicationInitialized = true;
        }

        // Do not add any additional code to this method
        private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e)
        {
            // Set the root visual to allow the application to render
            if (this.RootVisual != this.RootFrame)
            {
                this.RootVisual = this.RootFrame;
            }

            // Remove this handler since it is no longer needed
            this.RootFrame.Navigated -= this.CompleteInitializePhoneApplication;
        }

        /// <summary>See <see cref="ICryptoProvider"/>.</summary>
        private sealed class CryptoProvider : ICryptoProvider
        {
            /// <summary>See <see cref="ICryptoProvider.Encrypt"/>.</summary>
            public byte[] Encrypt(byte[] input)
            {
                return input == null ? null : ProtectedData.Protect(input, null);
            }

            /// <summary>See <see cref="ICryptoProvider.Decrypt"/>.</summary>
            public byte[] Decrypt(byte[] input)
            {
                return input == null ? null : ProtectedData.Unprotect(input, null);
            }
        }
    }
}